home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turnbull China Bikeride
/
Turnbull China Bikeride - Disc 2.iso
/
STUTTGART
/
TEX-UTIL
/
TEXUTILS
/
rtf2LaTeX
/
c
/
rtf2LaTeX
< prev
Wrap
Text File
|
1996-09-03
|
68KB
|
2,809 lines
/*
* An output filter to produce LaTeX using Paul DuBois' RTF reader
* WECHTL Erwin
* Woerthg. 2/18
* A-2500 Baden
* AUSTRIA
*
* a student of the University in vienna
* Technische Universitaet Wien
* Institut fuer Technische Informatik
* Treitlstr. 3
* A-1040 WIEN
* AUSTRIA
*
* Changed code from:
*
* Written and copyright (c) 1991 by Robert Lupton (rhl@astro.princeton.edu)
* Permission is granted to freely distribute and modify this code, providing:
* 1/ This copyright notice is preserved
* 2/ You send me a copy of any changes for inclusion in a future release
*/
#include <stdio.h>
#ifdef __riscos
# include <4SharedC/ctype.h>
void *xosfile_set_type(char *, int);
#define FileType_TeX 0x2a7
#define FileType_LaTeX 0x2a8
#else
# include <ctype.h>
#endif
#include <string.h>
#ifdef __STDC__
# include <stdlib.h>
# ifndef THINK_C
# include <unistd.h>
# endif
#else /* !__STDC__ */
# ifdef NO_MALLOC_H
extern char *malloc ();
# else /* NO_MALLOC_H */
# include <malloc.h>
# endif /* NO_MALLOC_H */
#endif /* !__STDC__ */
#ifndef SEEK_SET
# define SEEK_SET 0
#endif
#include "fonts.h"
#include "r2L_version.h"
#include "rtf2LaTeX.h"
#include "rtf.h"
#ifdef THINK_C
#include <console.h>
#include "macintosh.h"
static char * RTFDIR;
#endif
#ifdef __riscos
char *RTFDIR = "RTFDIR:";
#endif
FILE *outfp = stdout; /* Changed - I don't like using stdout only */
char *progname; /* Used in Error messages */
RTFFuncPtr default_read_font = NULL; /* default func to read style table */
RTFFuncPtr default_read_style = NULL; /* default func to read style table */
/* This forward declaration isn't possible in the header file because
* RTFStyle isn't defined there yet.
*/
static int is_specialWORDstyle A((RTFStyle*,LATEXStyle*));
/*****************************************************************************/
int
main(ac,av)
int ac;
char *av[];
{
RTF_STACK rtf_initial; /* initial values of things that
on rtf stack */
static char *header_erwinbet[] = {
"% Converted from RTF format using rtf2LaTeX",
"% Comments and bugs to Erwin Wechtl",
"% Woertg. 2/18",
"% A-2500 Baden",
"%",
NULL,
};
FILE *fil = NULL;
extern int optind;
extern char *optarg;
int c;
char *codefile = "ansi", *landfile = "english";
char *str = "12345.67";
char *rtf_filename = NULL;
#ifdef THINK_C
RTFDIR = get_home_dir();
ac = ccommand(&av);
#endif /* THINK_C */
progname = av[0];
#ifdef __riscos
while((c = getopt(ac,av,"cC:dhgGHL:no:pqrR:stT:uv:V")) != EOF)
#else
while((c = getopt(ac,av,"cC:dhgGHL:no:pqrstT:uv:V")) != EOF)
#endif
{
switch (c)
{
case 'g':
german_squotes = 1;
break;
case 'G':
german_dquotes = 1;
break;
case 'q':
translate_quotes = 1;
break;
case 'C':
codefile = optarg;
break;
case 'c': /* don't do character formating */
formatting_char= 0;
break;
case 'd': /* formate also in specila WORD styles like heading, footer, footnote text, .. (default 0) */
formatting_sWORD = 1;
break;
case 'h':
usage();
exit(0);
case 'H': /* use LaTeX default header and footer */
header_on = 0;
break;
case 'L':
landfile = optarg;
break;
case 'n':
other_linebreak = 1; /* use \hfil\break instead of \\ */
break; /* for making a new line */
case 'o':
if ((outfp = fopen(optarg,"w")) == NULL) /* modified for more convenience */
{
fprintf(stderr,"Error opening output file %s\n",optarg);
exit(0);
}
osfile_set_type(optarg,FileType_LaTeX);
break;
case 'p': /* don't do paragraph formating */
formatting_para = 0;
break;
case 'r': /* ignore left and right skip */
rl_skip_on = 0;
break;
#ifdef __riscos
case 'R':
RTFDIR = optarg;
break;
#endif
case 's': /* ignore tab stops */
tabstops_on = 0;
break;
case 't': /* don't do any formating in tables */
formatting_table = 0;
break;
case 'T': /* decrease cell-width (default 0.7)*/
smaller_cell_factor=atof(optarg);
if (!(smaller_cell_factor > 0))
{
fprintf(stderr,"\n%s: Argument of the -T flag must be greater than 0,\n but it is %g\n", progname, smaller_cell_factor);
fprintf(stderr,"use -h for help\n");
exit(2);
}
break;
case 'u': /* change underline to italic */
noUnderline = 1;
break;
case 'v':
verbose = atoi(optarg);
if (verbose!=1 && verbose!=2)
{
fprintf(stderr,"\n%s: The level of verbose can only be 1 or 2\n", progname);
fprintf(stderr,"use -h for help\n");
exit(2);
}
break;
case 'V':
fprintf(stderr,"%s: %s\n",progname,version);
exit(0);
break;
case '?':
fprintf(stderr,"%s: ", progname);
usage();
exit(2);
}
}
if (optind<ac)
{
if ((strchr(av[optind],'.')) != NULL)
rtf_filename = av[optind];
else
{
if((rtf_filename = malloc(strlen(av[optind]) + 5)) == NULL)
{
fprintf(stderr,"%s: Error in malloc\n", progname);
exit(3);
}
strcpy(rtf_filename, av[optind]);
#ifdef __riscos
strcat(rtf_filename,"/rtf");
#else
strcat(rtf_filename,".rtf");
#endif
}
}
#ifdef THINK_C
else rtf_filename = get_file_from_dialog();
if (!rtf_filename) exit(0);
#endif
if(rtf_filename != NULL)
{
if((fil = fopen(rtf_filename,"r")) == NULL)
{
fprintf(stderr,"%s: Can't open %s\n",progname,rtf_filename);
exit(1);
}
RTFSetStream(fil);
}
if (optind+1<ac)
{
fprintf(stderr,"%s: After the filename (%s) there are no more arguments or flags allowed!\n", progname, av[optind]);
fprintf(stderr,"use -h for help\n");
exit(2);
}
rtf_default.LaTeX_stack = NULL; /* the rtf stack */
rtf_default.char_attr = char_attr;
rtf_default.par_attr = par_attr;
rtf_default.style = -1;
rtf_default.prev = NULL;
rtf_current = rtf_initial = rtf_default;
rtf_ptr=&rtf_default;
tabinitold[0]=tabinitnew[0]='\0';
Cformatting_char=formatting_char;
Cformatting_para=formatting_para;
tabstopsInit();
RTFInit();
read_code_file(codefile); /* the file with the characters above 126
files have the extension .code
default file mac.code
use flag -C for other files
e.g ansi.code*/
open_land_file(landfile); /* the file with the special WORD styles
footer, footnote text, heading, ...
files have the extension .land
default file english.land
use flag -L for other files
e.g german.land */
print_text(header_erwinbet,outfp);
output_str("\\documentstyle",'\0');
if(german_squotes || german_dquotes)
output_str("[german]",'\0');
output_str("{article}\n",'\0');
if(header_on)
{
output_str("\\pagestyle",'\0');
output_str("{myheadings}\n",'\0');
}
output_str("\\newlength{\\defaultparindent}\n",'\0');
output_str("\\setlength{\\defaultparindent}{\\parindent}\n",'\0');
default_read_font = RTFGetDestinationCallback(rtfFontTbl);
(void)RTFSetClassCallback(rtfUnknown, UnknownClass);
(void)RTFSetClassCallback(rtfGroup, GroupClass);
(void)RTFSetClassCallback(rtfText, start_para);
(void)RTFSetClassCallback(rtfControl, ControlClass);
(void)RTFSetDestinationCallback(rtfPict, read_pict);
RTFRead();
if(rtf_group != 0) {
fprintf(stderr,"%s: End of file is in an unclosed RTF group (level %d)\n",
progname,rtf_group);
}
if(LaTeX_group != 0) {
fprintf(stderr,"%s: End of file is in an unclosed LaTeX group (level %d)\n",
progname,LaTeX_group);
}
if(quotecount % 2)
{
fprintf(stderr,"%s: Uneven number of quotes (%d) counted\n",
progname, quotecount);
}
if(fil != NULL) fclose(fil);
output_str("\\end{document}",'\0');
if (verbose)
fprintf(stderr,"\nIf there are any LaTeX errors or warnings,\n\
have a look in the man page section troubleshooting \n\n");
return(0);
}
/*****************************************************************************
*
* Token class callbacks
*/
static void
UnknownClass()
{
fprintf(stderr,"%s: Unknown Token: %s\n",progname,rtfTextBuf);
}
/*****************************************************************************/
static void
GroupClass()
{
switch (rtfMajor) {
case rtfBeginGroup:
if(initialised && !text_out) {
start_para();
}
if (!table_mode) /*it's hard to know where the end of */
end_table(); /* a table is, maybe here */
push_rtf_group();
rtf_group++;
break;
case rtfEndGroup:
if(--rtf_group == -1) {
fprintf(stderr,"%s: Unbalanced group\n", progname);
} else {
while(pop_LaTeX_stack()) continue;
pop_rtf_group();
if(end_of_par) {
end_para();
}
}
break;
}
}
static void
initialise()
{
inDefineStyle=TRUE;
DefineStyles();
inDefineStyle=FALSE;
if(pageno != 1) {
sprintf(buff,"\\setcounter{page}{%d}\n",pageno);
output_str(buff,'\0');
}
output_str("\n%*****************************************************************",'\0');
output_str("\n\\begin{document}\n",'\0');
tabstopsInit();
initialised = 1; /* don't do it twice */
}
/*****************************************************************************/
static void
TextClass()
{
output(rtfMajor,1);
}
/*****************************************************************************
*
* Process control symbol.
*/
static void
ControlClass()
{
switch (rtfMajor) {
case rtfVersion:
if(verbose) fprintf(stderr,"RTF version %d\n",rtfParam);
break;
case rtfDefFont:
default_font = rtfParam; /* this may not be in the font table */
break;
case rtfCharSet:
CharSet ();
break;
case rtfDestination:
Destination();
break;
case rtfFontFamily: /* only occurs within font table */
fprintf(stderr,"%s: You shouldn't see rtfFontType: minor %d\n",
progname,rtfMinor);
break;
case rtfColorName: /* only occurs within color table */
fprintf(stderr,"%s: You shouldn't see rtfColorName: minor %d\n",
progname,rtfMinor);
break;
case rtfStyleAttr: /* only occurs within stylesheet */
switch (rtfMinor) {
case rtfBasedOn:
if(rtfParam != rtfNoParam) {
static int count = 0;
if(verbose > 1 || (verbose && count++ == 0)) {
msg_not_yet("sbasedon");
}
}
break;
case rtfNext:
if(rtfParam != rtfNoParam) {
static int count = 0;
if(verbose > 1 || (verbose && count++ == 0)) {
msg_not_yet("snext");
}
}
break;
default:
fprintf(stderr,"%s: Illegal minor number for StyleAttr: %d\n",
progname,rtfMinor);
break;
}
break;
case rtfSpecialChar:
SpecialChar();
break;
case rtfDocAttr:
DocAttr();
break;
case rtfSectAttr:
SectAttr();
break;
case rtfTblAttr:
TblAttr();
break;
case rtfParAttr:
ParAttr();
break;
case rtfCharAttr:
if (Cformatting_char)
CharAttr();
break;
case rtfPictAttr:
fprintf(stderr,"%s: You shouldn't see rtfPictAttr: minor %d\n",
progname,rtfMinor);
break;
case rtfFieldAttr:
FieldAttr();
break;
case rtfTOCAttr:
TOCAttr();
break;
case rtfPosAttr:
PosAttr();
break;
}
}
/*****************************************************************************
*
* Control class major number handlers. Each one switches on the
* minor numbers that occur within the major number. rtfStyleSheet,
* rtfFontTbl, and rtfColorTbl are not in the switch because they're
* handled by the reader. rtfPict has its own callback.
*/
static void
CharSet()
{
switch (rtfMinor) {
case rtfAnsiCharSet:
break;
case rtfMacCharSet:
break;
case rtfPcCharSet:
break;
case rtfPcaCharSet:
break;
}
}
static void
Destination()
{
switch (rtfMinor) {
case rtfFootnote:
output_str("%\n",'\0');
output_str("\\footnote{",'\0');
push_LaTeX_stack("}%\n",Footnote,0);
break;
case rtfHeader:
if (!initialised)
initialise();
if (header_on)
{
output_str("\\markright{",'\0');
push_LaTeX_stack(" }\n",Header,0);
}
else
{
RTFSkipGroup();
RTFUngetToken();
}
break;
case rtfHeaderLeft:
case rtfHeaderRight:
case rtfHeaderFirst:
if (verbose)
msg_not_supported(rtfTextBuf+1);
break;
case rtfFooter:
if (header_on)
{
if (verbose)
fprintf(stderr,"LaTeX supports only the header\n");
output_str("% LaTeX supports only the header\n",'\0');
}
RTFSkipGroup();
RTFUngetToken();
break;
case rtfFooterLeft:
break;
case rtfFooterRight:
break;
case rtfFooterFirst:
break;
case rtfFNSep:
break;
case rtfFNContSep:
break;
case rtfFNContNotice:
break;
case rtfInfo:
break;
case rtfField:
break;
case rtfFieldInst:
{
char buf[80];
buf[0]='\0';
(void)RTFGetToken();
while(rtfClass==rtfText)
{
strcat(buf,rtfTextBuf);
(void)RTFGetToken();
}
RTFUngetToken();
if (strncmp(buf,"date",4)==0)
output_str("\\today",'\0');
else
if (verbose)
{
char msg_buf[80];
strcpy(msg_buf,rtfTextBuf+1);
strcat(msg_buf,buf);
msg_not_yet(msg_buf);
}
break;
}
break;
case rtfFieldResult:
break;
case rtfIndex:
break;
case rtfIndexBold:
break;
case rtfIndexItalic:
break;
case rtfIndexText:
break;
case rtfIndexRange:
break;
case rtfTOC:
break;
case rtfBookmarkStart:
break;
case rtfBookmarkEnd:
break;
case rtfITitle:
(void) RTFGetToken ();
while (rtfClass == rtfText)
(void) RTFGetToken ();
RTFUngetToken();
break;
case rtfISubject:
(void) RTFGetToken ();
while (rtfClass == rtfText)
(void) RTFGetToken ();
RTFUngetToken();
break;
case rtfIAuthor:
(void) RTFGetToken ();
while (rtfClass == rtfText)
(void) RTFGetToken ();
RTFUngetToken();
break;
case rtfIOperator:
break;
case rtfIKeywords:
(void) RTFGetToken ();
while (rtfClass == rtfText)
(void) RTFGetToken ();
RTFUngetToken();
break;
case rtfIComment:
(void) RTFGetToken ();
while (rtfClass == rtfText)
(void) RTFGetToken ();
RTFUngetToken();
break;
case rtfIVersion:
break;
case rtfIVerscomm:
/* \verscomm is a token, made by Macintosh's WORD.
* I don't know the meaning,
* because it isn't specified in the RTF-specification.
*/
RTFSkipGroup();
RTFUngetToken();
break;
case rtfIDoccomm:
(void) RTFGetToken ();
while (rtfClass == rtfText)
(void) RTFGetToken ();
RTFUngetToken();
break;
}
}
static void
SpecialChar()
{
switch (rtfMinor) {
case rtfCurHeadPage:
if (verbose && header_on)
fprintf(stderr,"LaTeX always puts the page number in right corner\n");
break;
case rtfCurFNote:
{
static int count=0;
if (verbose && count++ == 0)
msg_not_needed(rtfTextBuf+1);
break;
}
case rtfCurHeadPict:
msg_not_supported("chpict");
break;
case rtfCurHeadDate:
case rtfCurHeadTime:
if (verbose)
msg_not_supported(rtfTextBuf+1);
break;
case rtfFormula:
msg_not_yet("|");
break;
case rtfNoBrkSpace:
if(!text_out) start_para();
output_str("~",'\0');
break;
case rtfNoReqHyphen:
output_str("\\-",'\0');
break;
case rtfNoBrkHyphen:
if(!text_out) start_para();
output('-',1);
break;
case rtfPage:
end_para();
end_table(); /* if there is a table */
output_str("\n\\newpage\n",'\0');
break;
case rtfLine:
if (!other_linebreak)
output_str("\\\\ \n",'\0');
else
output_str(" \\hfill \\break \n",'\0');
break;
case rtfPar:
if (top_LaTeX_flags(Header))
{
if (!other_linebreak)
output_str("\\\\ \n",'\0');
else
output_str(" \\hfill \\break \n",'\0');
return;
}
if (top_LaTeX_flags(SpecialWORDstyle))
pop_LaTeX_stack();
if (tab==2 && text_out)
{
while (!top_LaTeX_flags(Tabstops) )
if (pop_LaTeX_stack()==0) break;
rtf_current=rtf_default;
output_str("\\\\ \n",'\0');
update_current();
}
/* we may want to deal with this
elsewhere, so as to pop the stacks
before printing the newline */
RTFGetToken();
if(RTFCheckCM(rtfGroup,rtfEndGroup) ||
RTFCheckCMM(rtfControl,rtfParAttr,rtfParDef)) {
end_of_par = 1;
/* Don't know if this one is needed anymore
* } else if(in_table && RTFCheckCMM(rtfControl,rtfSpecialChar,rtfPar)) {
* end_table(); * two \par's in a row *
*/
} else {
end_para();
}
RTFUngetToken();
break;
case rtfSect:
rtfMinor = rtfPar; /* pretend that it's just a para */
RTFUngetToken();
break;
case rtfTab:
if (top_LaTeX_flags(SpecialWORDstyle))
return; /* no tab stops in header, haeding, ...*/
if(!text_out) start_para();
if (!tabstops_on)
break;
if (tab)
{
while (!top_LaTeX_flags(Tabstops) )
if (pop_LaTeX_stack()==0) break;
rtf_current=rtf_default;
output_str("\\> ",'\0');
update_current();
}
else
{
output(' ',1);
if (verbose && tabstops_on)
fprintf(stderr,"this tab stop is ignored\n you have to specify the position of the tab stop before\n");
}
break;
case rtfCell:
while (!top_LaTeX_flags(Tabular) )
if (pop_LaTeX_stack()==0) break;
rtf_current=rtf_default;
cellnr++;
if (cellnr<max_cellnr)
output_str(" & ",'\0');
update_current();
break;
case rtfRow:
while (!top_LaTeX_flags(Tabular) )
if (pop_LaTeX_stack()==0) break;
rtf_current=rtf_default;
cellnr=0;
output_str("\\\\",'\0');
output('\n',1);
update_current();
break;
case rtfCurAnnot:
break;
case rtfAnnotation:
break;
case rtfAnnotID:
break;
case rtfCurAnnotRef:
break;
case rtfFNoteSep:
break;
case rtfFNoteCont:
break;
case rtfColumn:
break;
case rtfOptDest:
break;
case rtfIIntVersion:
break;
case rtfICreateTime:
break;
case rtfIRevisionTime:
break;
case rtfIPrintTime:
break;
case rtfIBackupTime:
break;
case rtfIEditTime:
break;
case rtfIYear:
break;
case rtfIMonth:
break;
case rtfIDay:
break;
case rtfIHour:
break;
case rtfIMinute:
break;
case rtfINPages:
break;
case rtfINWords:
break;
case rtfINChars:
break;
case rtfIIntID:
break;
case rtfBullet:
output_str("\\bullet ",'\0');
break;
case rtfEmDash:
output_str("---",'\0');
break;
case rtfEnDash:
output_str("--",'\0');
break;
case rtfLQuote:
if(german_squotes)
output_str("\\glq ",'\0');
else
output_str("`",'\0');
break;
case rtfRQuote:
if(german_squotes)
output_str("\\grq ",'\0');
else
output_str("'",'\0');
break;
case rtfLDblQuote:
if(german_dquotes)
output_str("\"`",'\0');
else
output_str("``",'\0');
break;
case rtfRDblQuote:
if(german_dquotes)
output_str("\"'",'\0');
else
output_str("''",'\0');
break;
}
}
static void
DocAttr()
{
switch (rtfMinor) {
case rtfPaperWidth:
case rtfPaperHeight:
case rtfLeftMargin:
case rtfRightMargin:
case rtfTopMargin:
case rtfBottomMargin:
{
static int count = 0;
if(verbose > 1 || (verbose && count++ == 0)) {
msg_not_yet(rtfTextBuf+1);
}
}
break;
case rtfFacingPage:
if(verbose)
msg_not_yet(rtfTextBuf+1);
break;
case rtfGutterWid:
msg_not_yet("gutter");
break;
case rtfDefTab:
msg_not_yet("deftab");
break;
case rtfWidowCtrl:
msg_not_yet("widowctrl");
break;
case rtfFNoteEndSect:
msg_not_yet("endnotes");
break;
case rtfFNoteEndDoc:
break;
case rtfFNoteBottom:
break;
case rtfFNoteText:
msg_not_yet("ftntj");
break;
case rtfFNoteStart:
if(footnote_num0 != rtfParam) {
footnote_num0 = rtfParam;
change_headfoot = 1;
}
break;
case rtfFNoteRestart:
if(footnotes_restart_each_page != 1) {
footnotes_restart_each_page = 1;
change_headfoot = 1;
}
break;
case rtfHyphHotZone:
break;
case rtfPageStart:
pageno = rtfParam;
break;
case rtfLineStart:
lineno = rtfParam;
break;
case rtfLandscape:
msg_not_supported("landscape");
break;
case rtfFracWidth:
break;
case rtfNextFile:
break;
case rtfTemplate:
break;
case rtfMakeBackup:
break;
case rtfRTFDefault:
break;
case rtfRevisions:
break;
case rtfMirrorMargin:
break;
case rtfRevDisplay:
break;
case rtfRevBar:
break;
}
}
/*****************************************************************************/
static void
SectAttr()
{
switch (rtfMinor) {
case rtfSectDef:
set_headfoot_lines();
break;
case rtfNoBreak:
break;
case rtfColBreak:
break;
case rtfPageBreak:
break;
case rtfEvenBreak:
break;
case rtfOddBreak:
break;
case rtfPageStarts:
break;
case rtfPageCont:
break;
case rtfPageRestart:
break;
case rtfPageDecimal:
if(pageno_style != Pageno_Decimal) {
pageno_style = Pageno_Decimal;
change_headfoot = 1;
}
break;
case rtfPageURoman:
if(pageno_style != Pageno_URoman) {
pageno_style = Pageno_URoman;
change_headfoot = 1;
}
break;
case rtfPageLRoman:
if(pageno_style != Pageno_LRoman) {
pageno_style = Pageno_LRoman;
change_headfoot = 1;
}
break;
case rtfPageULetter:
msg_not_yet("pgnucltr");
break;
case rtfPageLLetter:
msg_not_yet("pgnlcltr");
break;
case rtfPageNumLeft:
if(pageno_x != rtfParam) {
pageno_x = rtfParam;
change_headfoot = 1;
}
break;
case rtfPageNumTop:
if(pageno_y != rtfParam) {
pageno_y = rtfParam;
change_headfoot = 1;
}
break;
case rtfLineModulus:
if(rtfParam != 0) msg_not_supported("linemod");
break;
case rtfLineStarts:
break;
case rtfLineDist:
msg_not_supported("linex");
break;
case rtfLineRestart:
msg_not_supported("linerestart");
break;
case rtfLineRestartPg:
msg_not_supported("lineppage");
break;
case rtfLineCont:
msg_not_supported("linecont");
break;
case rtfHeaderY:
msg_not_yet("headery");
break;
case rtfFooterY:
msg_not_yet("footery");
break;
case rtfTopVAlign:
break;
case rtfBottomVAlign:
break;
case rtfCenterVAlign:
break;
case rtfJustVAlign:
break;
case rtfColumns:
if(rtfParam != 1) msg_not_yet("cols");
break;
case rtfColumnLine:
break;
case rtfColumnSpace:
msg_not_yet("colsx");
break;
case rtfENoteHere:
msg_not_supported("endnhere");
break;
case rtfTitleSpecial:
msg_not_supported("titlepg");
break;
}
}
static void
TblAttr()
{
switch (rtfMinor) {
case rtfCellBordBottom:
case rtfCellBordTop:
case rtfCellBordLeft:
case rtfCellBordRight:
{
static int count = 0;
if(verbose > 1 || (verbose && count++ == 0)) {
msg_not_yet(rtfTextBuf+1);
}
}
break;
case rtfRowDef:
table_mode=1;
push_LaTeX_stack("",TabularInit,1);
strcpy(tabinitnew,"\n\\begin{tabular}{");
endOfLastCell=-70;
max_cellnr=0;
break;
case rtfRowLeft:
case rtfRowRight:
case rtfRowCenter:
case rtfRowGapH:
case rtfRowHt:
case rtfRowLeftEdge:
{
static int count = 0;
if(verbose > 1 || (verbose && count++ == 0)) {
msg_not_yet(rtfTextBuf+1);
}
}
break;
case rtfCellPos:
{
unsigned int cell_bright;
max_cellnr++;
cell_bright=(rtfParam-endOfLastCell)*smaller_cell_factor;
sprintf(buff,"p{%gpt}",TW_TO_PT(cell_bright));
strcat(tabinitnew,buff);
endOfLastCell=rtfParam;
break;
}
case rtfCellShading:
/* \clshdng is a token, made by Macintosh's WORD
* I don't know the meaning,
* because it isn't specified in the RTF-specification
*/
break;
case rtfMergeRngFirst:
break;
case rtfMergePrevious:
break;
}
}
/*****************************************************************************/
static void
ParAttr()
{
switch (rtfMinor) {
case rtfParDef:
if(!initialised) { /* it's hard to know where to call it*/
initialise();
}
while(top_LaTeX_flags(Font) || top_LaTeX_flags(Font_Num) ||
top_LaTeX_flags(Font_Size) || top_LaTeX_flags(Style) ||
top_LaTeX_flags(Undefined) || top_LaTeX_flags(Underline) ||
top_LaTeX_flags(Sub_Super) ||
top_LaTeX_flags(Paragraph) ||
top_LaTeX_flags(NormalWORDstyle) ||
top_LaTeX_flags(LRskip) || top_LaTeX_flags(SpecialWORDstyle)) {
(void)pop_LaTeX_stack();
}
rtf_current.par_attr.leftskip=rtf_current.par_attr.rightskip=0;
if (top_LaTeX_flags(Tabstops))
{
(void)pop_LaTeX_stack();
Cformatting_char=formatting_char;
Cformatting_para=formatting_para;
}
if (!table_mode && top_LaTeX_flags(Tabular))
end_table(); /* it's hard to know where to call it*/
if ((table_mode) && /* begin of a table in rtf */
top_LaTeX_flags(TabularInit) )
if (strcmp(tabinitold,tabinitnew)==0)
{ /*we haven't finished the last */
(void)pop_LaTeX_stack(); /* table in LaTeX and the parameters */
} /* of both the current and last */
/* rtf-table are equal so we needn't */
/* start a new LaTeX-table */
else
{
end_table(); /* we will have to finish the last table, if there is one */
strcpy(tabinitold,tabinitnew);
table_mode=1;
output_str(tabinitnew,'\0'); /* and to start a new one */
output_str("}\n",'\0');
push_LaTeX_stack("\\end{tabular}\n",Tabular,0);
Cformatting_char=formatting_char&&formatting_table;
Cformatting_para=formatting_para&&formatting_table;
}
if(end_of_par /*&& !table_mode*/) {
end_para();
}
ntabs = 0;
table_mode=0;
tab=0;
rtf_default.LaTeX_stack = rtf_ptr->LaTeX_stack;
rtf_default.prev = rtf_ptr->prev;
*rtf_ptr = rtf_default;
rtf_current.char_attr = rtf_default.char_attr;
(void)RTFSetClassCallback(rtfText, start_para); /* not really start a new pragraph
but have a look if there is a
table end */
break;
case rtfStyleNum:
if(inDefineStyle)
RTFExpandStyle(rtfParam);
else
{
if(!initialised)
{ /* it's hard to know where to call it*/
RTFUngetToken(); /* store the Token, because initialise */
initialise(); /* changes it */
RTFGetToken();
}
if (!table_mode && top_LaTeX_flags(Tabular))
end_table(); /* it's hard to know where to call it*/
setstylecommand(rtfParam);
}
break;
case rtfQuadLeft:
{
static int count = 0;
if(verbose > 1 || (verbose && count++ == 0)) {
msg_map_to("gl","gj");
}
rtf_ptr->par_attr.flags |= LeftAlign;
}
break;
case rtfQuadRight:
if (text_out)
{
if (!Cformatting_para) /* no paragraph formatting */
break;
output_str("\n\\begin{flushright}",'\0');
push_LaTeX_stack("\n\\end{flushright}",Paragraph,0);
}
else
rtf_ptr->par_attr.flags |= RightAlign;
break;
case rtfQuadJust:
rtf_ptr->par_attr.flags &= ~(LeftAlign | Centred | RightAlign);
break;
case rtfQuadCenter:
if (text_out)
{
if (!Cformatting_para) /* no paragraph formatting */
break;
output_str("\n\\begin{center}",'\0');
push_LaTeX_stack("\n\\end{center}",Paragraph,0);
}
else
rtf_ptr->par_attr.flags |= Centred;
break;
case rtfFirstIndent:
rtf_ptr->par_attr.parindent = rtfParam;
break;
case rtfLeftIndent:
rtf_ptr->par_attr.leftskip = rtfParam;
break;
case rtfRightIndent:
rtf_ptr->par_attr.rightskip = rtfParam;
break;
case rtfSpaceBefore:
rtf_ptr->par_attr.skip_before = rtfParam;
break;
case rtfSpaceAfter:
rtf_ptr->par_attr.skip_after = rtfParam;
break;
case rtfSpaceBetween:
break;
case rtfInTable:
table_mode=1;
break;
case rtfKeep:
break;
case rtfKeepNext:
break;
case rtfSideBySide:
break;
case rtfPBBefore:
break;
case rtfNoLineNum: /* ignored */
break;
case rtfBorderTop:
break;
case rtfBorderBottom:
break;
case rtfBorderLeft:
break;
case rtfBorderRight:
break;
case rtfBorderBar:
break;
case rtfBorderBox:
break;
case rtfBorderBetween:
break;
case rtfBorderSingle:
break;
case rtfBorderThick:
break;
case rtfBorderShadow:
break;
case rtfBorderDouble:
break;
case rtfBorderDot:
break;
case rtfBorderHair:
break;
case rtfBorderSpace:
break;
case rtfTabPos:
if (top_LaTeX_flags(SpecialWORDstyle))
return; /*no tab stops in header, heading, ...*/
if (!tabstops_on)
break;
if (!table_mode && top_LaTeX_flags(Tabular))
end_table();
if (table_mode)
{
if (verbose)
fprintf(stderr,"can't deal with tab stops in tables");
}
else
{
tab=1;
if(ntabs >= NTABS) {
if(ntabs == NTABS)
fprintf(stderr,"%s: Attempt to set more than %d tabs\n",
progname,NTABS);
} else {
tabstops[ntabs++].pos = rtfParam;
tabstops[ntabs].type = TabLeft;
}
}
break;
case rtfTabRight:
if(ntabs < NTABS) {
tabstops[ntabs].type = TabRight;
}
break;
case rtfTabCenter:
if(ntabs < NTABS) {
tabstops[ntabs].type = TabCentre;
}
break;
case rtfTabDecimal:
if(ntabs < NTABS) {
tabstops[ntabs].type = TabDecimal;
}
break;
case rtfTabBar:
{
static int count = 0;
if(verbose > 1 || (verbose && count++ == 0))
msg_not_yet("tb");
}
break;
case rtfLeaderDot:
break;
case rtfLeaderHyphen:
break;
case rtfLeaderUnder:
break;
case rtfLeaderThick:
break;
}
}
/*procedure not needed yet*/
static void PictAttr ()
{
switch (rtfMinor) {
case rtfMacQD:
break;
case rtfWinMetafile:
break;
case rtfWinBitmap:
break;
case rtfPicWid:
break;
case rtfPicHt:
break;
case rtfPicGoalWid:
break;
case rtfPicGoalHt:
break;
case rtfPicScaleX:
break;
case rtfPicScaleY:
break;
case rtfPicScaled:
break;
case rtfPicCropTop:
break;
case rtfPicCropBottom:
break;
case rtfPicCropLeft:
break;
case rtfPicCropRight:
break;
case rtfPixelBits:
break;
case rtfBitmapPlanes:
break;
case rtfBitmapWid:
break;
case rtfPicBinary:
break;
}
}
/*****************************************************************************/
static void
FieldAttr()
{
switch (rtfMinor) {
case rtfFieldDirty:
break;
case rtfFieldEdited:
break;
case rtfFieldLocked:
break;
case rtfFieldPrivate:
break;
}
}
/*****************************************************************************/
static void
TOCAttr()
{
switch (rtfMinor) {
case rtfTOCType:
break;
case rtfTOCLevel:
break;
}
}
/*****************************************************************************/
static void
PosAttr()
{
switch (rtfMinor) {
case rtfPosX:
break;
case rtfPosXCenter:
break;
case rtfPosXInside:
break;
case rtfPosXLeft:
break;
case rtfPosXOutSide:
break;
case rtfPosXRight:
break;
case rtfPosY:
break;
case rtfPosYInline:
break;
case rtfPosYTop:
break;
case rtfPosYCenter:
break;
case rtfPosYBottom:
break;
case rtfAbsWid:
break;
case rtfTextDist:
break;
case rtfRPosMargV:
break;
case rtfRPosPageV:
break;
case rtfRPosMargH:
break;
case rtfRPosPageH:
break;
case rtfRPosColH:
break;
}
}
/*****************************************************************************
*
* Deal with Pict destinations
*/
static void
read_pict()
{
static int count=0;
if (verbose && count++==0)
fprintf(stderr,"%s: Don't support any picture-things yet; be patient\n",
progname);
if (verbose>1)
msg_not_yet(rtfTextBuf+1);
RTFSkipGroup ();
RTFRouteToken (); /* feed "}" back to router */
}
/*****************************************************************************
*
* Deal with things like footnote numbering and page numbers; things
* that involve the headline or footline
*/
static void
set_headfoot_lines()
{
int pageno_top = (pageno_y < paper_height/2 ? 1 : 0);
if(!change_headfoot) return;
# ifdef notdef /* I think this is left over from rtf2tex */
/*
* The headline first
*
output_str("\\headline={\\tenrm ",'\0');
if(footnotes_restart_each_page) {
sprintf(buff,"\\footnum=%d",footnote_num0);
output_str(buff,' ');
}
if(pageno_top) {
sprintf(buff,"\\kern %gpt %s\\hfil",TW_TO_PT(pageno_x),page_num());
output_str(buff,' ');
}
output_str("}",'\n');
/*
* And now the foot
*
output_str("\\footline={\\tenrm ",'\0');
if(!pageno_top) {
sprintf(buff,"\\kern %gpt %s\\hfil",TW_TO_PT(pageno_x),page_num());
output_str(buff,' ');
}
output_str("}",'\n');
change_headfoot = 0; /* we've done it *
*/
# endif /* notdef */
}
/*****************************************************************************
*
* Convert the pageno to the desired form
*/
static char *
page_num()
{
switch (pageno_style) {
case Pageno_Decimal:
return("\\number\\pageno");
case Pageno_LRoman:
return("\\romannumeral\\pageno");
case Pageno_URoman:
return("\\uppercase\\expandafter{\\romannumeral\\pageno}");
default:
return("");
}
}
/*****************************************************************************
*
* This is called when we see the first text token after each \par
*/
#define CURRENT(WHAT) /* is WHAT up-to-date? */ \
(rtf_current.WHAT == rtf_ptr->WHAT)
static void
start_para()
{
if(!initialised) { /* this could be the place */
initialise();
}
if(!table_mode && top_LaTeX_flags(Tabular))
end_table();
if (tab==1 && !table_mode)
start_tabstops();
update_current();
text_out = 1;
(void)RTFSetClassCallback(rtfText, TextClass);
if(rtfClass == rtfText) {
RTFUngetToken(); /* re-schedule the text */
}
}
/*
* End a paragraph
*/
static void
end_para()
{
if(in_table) {
tab_num = 0;
} else {
if (top_LaTeX_flags(SpecialWORDstyle) || top_LaTeX_flags(Header))
pop_LaTeX_stack();
output('\n',1);
output('\n',1);
}
text_out = 0;
end_of_par = 0;
(void)RTFSetClassCallback(rtfText, start_para);
}
/*****************************************************************************
*
* Force an update of the current state, only emitting commands
* that actually change anything.
*/
static void
update_current()
{
RTFStyle *style;
if (Cformatting_char)
{
if(!CURRENT(char_attr.FontSize))
set_fontsize(rtf_ptr->char_attr.FontSize);
if(!CURRENT(char_attr.sub_super_height))
set_subsuper(rtf_ptr->char_attr.sub_super_height);
if(!CURRENT(char_attr.smallcaps))
set_smallcaps();
if(!CURRENT(char_attr.font))
if(rtf_ptr->char_attr.font == Bold) {
if (initialised)
set_font(Bold,1,"\n{\\bf ","}");
else
set_font(Bold,1,"\n\\bf ","");
}
if(!CURRENT(char_attr.font))
if(rtf_ptr->char_attr.font == Italic) {
if (initialised)
set_font(Italic,1,"\n{\\it ","}");
else
set_font(Italic,1,"\n\\it ","");
}
}
if (Cformatting_para)
{
if(!CURRENT(par_attr.flags))
switch (rtf_ptr->par_attr.flags)
{
case Centred:
output_str("\n\\begin{center}",'\0');
push_LaTeX_stack("\n\\end{center}",Paragraph,0);
break;
case RightAlign:
output_str("\n\\begin{flushright}",'\0');
push_LaTeX_stack("\n\\end{flushright}",Paragraph,0);
break;
case LeftAlign:
output_str("\n\\begin{flushleft}",'\0');
push_LaTeX_stack("\n\\end{flushleft}",Paragraph,0);
break;
default: /* block modus (LaTeX default)*/
break;
}
if(!CURRENT(par_attr.parindent))
{
if (rtf_ptr->par_attr.parindent==LaTeXdefault)
sprintf(buff,"\n\\setlength{\\parindent}{\\defaultparindent}");
else
sprintf(buff,"\n\\setlength{\\parindent}{%gpt}",
TW_TO_PT(rtf_ptr->par_attr.parindent));
output_str(buff,'\0');
}
if (!CURRENT(par_attr.skip_before) ||
!CURRENT(par_attr.skip_after))
{
int skip;
skip=rtf_ptr->par_attr.skip_after+rtf_ptr->par_attr.skip_before;
sprintf(buff,"\n\\setlength{\\parskip}{%gpt}",
TW_TO_PT(skip));
output_str(buff,'\0');
}
if((!CURRENT(par_attr.leftskip) || !CURRENT(par_attr.rightskip)) &&
rl_skip_on)
{
if ((rtf_ptr->par_attr.leftskip!=0) ||
(rtf_ptr->par_attr.rightskip!=0) )
{
output_str("\n\\begin{list}",'\0');
output_str("{ }{",'\0');
sprintf(buff,"\n\\setlength{\\leftmargin}{%gpt}",
TW_TO_PT(rtf_ptr->par_attr.leftskip));
output_str(buff,'\0');
sprintf(buff,"\\setlength{\\rightmargin}{%gpt}",
TW_TO_PT(rtf_ptr->par_attr.rightskip));
output_str(buff,'\0');
output_str("\n\\setlength{\\topsep}{0pt}",'\0');
output_str("\\setlength{\\partopsep}{0pt}",'\0');
output_str("}\n\\item ",'\0');
push_LaTeX_stack("\n\\end{list}",LRskip,0);
}
}
}
rtf_current = *rtf_ptr;
rtf_current.LaTeX_stack = NULL;
rtf_current.prev = NULL;
}
/*****************************************************************************
*
* ALLDONE
*/
#define SET_FONT(FONT,START,END) /* set a Font */\
if(text_out && initialised) { \
set_font(FONT,(rtfParam == 0 ? 0 : 1),START,END); \
} \
rtf_ptr->char_attr.font = (rtfParam == 0 ? 0 : FONT);
#define SET_FONTSIZE(FONTSIZE) /* set a Fontsize */\
if(text_out && initialised) { \
set_fontsize(FONTSIZE); \
} \
rtf_ptr->char_attr.FontSize = FONTSIZE;
static void
CharAttr()
{
switch (rtfMinor) {
case rtfPlain:
if(text_out) {
while(top_LaTeX_flags(Underline) || top_LaTeX_flags(Sub_Super)
|| top_LaTeX_flags(Font) || top_LaTeX_flags(Font_Num))
(void)pop_LaTeX_stack();
}
rtf_ptr->char_attr = rtf_default.char_attr;
rtf_current.char_attr = rtf_default.char_attr;
break;
case rtfBold:
SET_FONT(Bold,"\n{\\bf ","}");
break;
case rtfItalic:
SET_FONT(Italic,"\n{\\it ","}");
break;
case rtfAllCaps:
{
static int count;
if(verbose > 1 || (verbose && count++ == 0)) {
msg_map_to("ac","sc");
}
}
case rtfSmallCaps:
if(text_out && initialised)
set_smallcaps();
rtf_ptr->char_attr.smallcaps = 1;
break;
case rtfStrikeThru:
case rtfOutline:
case rtfShadow:
case rtfInvisible:
{
static int count = 0;
if(verbose > 1 || (verbose && count == 0))
msg_not_supported(
rtfMinor == rtfStrikeThru ? "strike" :
rtfMinor == rtfOutline ? "outl" :
rtfMinor == rtfShadow ? "shad" :
rtfMinor == rtfInvisible ? "v" : "Unknown");
count++;
}
break;
case rtfFontNum:
break;
case rtfFontSize:
SET_FONTSIZE(rtfParam/2);
break;
case rtfDbUnderline:
case rtfDUnderline:
if (!noUnderline)
{
if (initialised)
{
output_str("\n\\underline{\\underline{",'\0');
push_LaTeX_stack("}}",Underline,0);
}
/* else doesn't work in LaTeX
{
output_str("\n\\underline \\bgroup \\underline \\bgroup",'\0');
push_LaTeX_stack("\\egroup \\egroup",Underline,0);
}
*/
break;
}
case rtfUnderline:
case rtfWUnderline:
{
static int count = 0;
if (!noUnderline)
{
if (initialised)
{
output_str("\n\\underline{",'\0');
push_LaTeX_stack("}",Underline,0);
}
/* else doesn't work in LaTeX
{
output_str("\n\\underline \\bgroup",'\0');
push_LaTeX_stack("\\egroup",Underline,0);
}
*/
}
else
{
if(verbose > 1 || (verbose && count++ == 0)) {
msg_map_to((rtfMinor == rtfUnderline ? "ul" : "ulw"),"i");
}
rtfMinor = rtfItalic;
CharAttr();
}
}
break;
case rtfNoUnderline:
break;
case rtfSubScript:
case rtfSuperScript:
if(rtf_ptr->char_attr.sub_super_height == rtfParam) break;
if(!text_out && initialised) start_para();
if(text_out && initialised) {
set_subsuper(rtfParam);
}
rtf_ptr->char_attr.sub_super_height = rtfParam;
break;
case rtfForeColor:
msg_not_supported("cf");
break;
case rtfBackColor:
break;
case rtfExpand:
msg_not_needed("expnd");
break;
case rtfRevised:
break;
}
}
/*****************************************************************************
*
* Various ways of refusing to deal with a keyword
*
*
* Treat \from as \to (e.g. treat \ul as \i)
*/
static void
msg_map_to(from,to)
char *from, *to;
{
if(verbose && !writing_defs) {
fprintf(stderr,"I'm going to treat \\%s as \\%s\n",from,to);
}
}
/*
* Keyword is neither needed by LaTeX or supported by rtf2LaTeX
* For example, \expnd to fiddle with inter-character spacing.
*/
static void
msg_not_needed(name)
char *name;
{
if(verbose && !writing_defs) {
fprintf(stderr,"\\%s is neither needed nor supported\n",name);
}
}
/*
* Keyword isn't supported, and probably can't be
* For example, \cf to change colours
*/
static void
msg_not_supported(name)
char *name;
{
static int pointer = 0;
for (pointer=0;(name[pointer]!='\0' && isalpha(name[pointer]));pointer++)
continue;
/* Should fix problem writing to string constants with gcc */
if(name[pointer] != '\0')
name[pointer]='\0'; /*No argument will be printed*/
if(verbose && !writing_defs) {
fprintf(stderr,"%s: Don't support \\%s; sorry\n",progname,name);
}
}
/*
* Keyword will be supported, but I haven't done it yet
*/
static void
msg_not_yet(name)
char *name;
{
if(verbose && !writing_defs) {
fprintf(stderr,"%s: Don't support \\%s yet; be patient\n",progname,name);
}
}
/*****************************************************************************
*
* Convert a string to a form that LaTeX can handle
*
* Remove spaces and capitalise the following letter,
* and converted digits to letters (1 --> A etc., 0 --> O)
*/
static char *
LaTeX_name(str)
char *str;
{
static char temp[50];
char *ptr;
for(ptr = temp;*str != '\0';str++) {
if(isspace(*str)) {
for(str++;isspace(*str);str++) continue;
if(*str == '\0') break;
*str = islower(*str) ? toupper(*str) : *str;
str--; continue; /* reprocess the character */
} else if(isdigit(*str)) {
if(*str == '0') *ptr++ = 'O';
else *ptr++ = *str + 'A' - '1';
} else {
*ptr++ = *str;
}
}
*ptr = '\0';
return(temp);
}
/*****************************************************************************/
static void
usage()
{
static char *msg[] = {
"Your options are:",
" -c No character formatting stuff",
" -C file Use another translation-file for characters above 128",
" -d Use WORD formates within special WORD styles ",
" like heading, footnote text, ...",
" -H Use LaTeX header and footer, not as default WORD header",
" -h This message",
" -L file Use another translation-file for specilal WORD styles",
" like heading, footer, footnote text, ...",
" -n Use \\hfill instead of \\\\ for making a new line",
" -o file Output to file",
" -p No paragraph formatting stuff",
" -r No left or right skip",
#ifdef __riscos
" -R path Path (or variable) pointing to the code and land directories",
#endif
" -s No tab stops",
" -t No formatting in tables",
" -T f Decrease-factor for the cell-width (default:0.7)",
" -u Change underline to italic",
" -v[#] Turn on verbose messages; the higher #, the more messages",
" -V Print the version number",
"If you omit the filename rtf2LaTeX will read standard input.",
"\nIf there are any LaTeX errors or warnings,",
"have a look in the man page section troubleshooting.\n ",
NULL,
};
fprintf(stderr, "Usage: %s [options] [RTF-file]\n", progname);
print_text(msg,stderr);
}
/*****************************************************************************
*
* print some text MSG to a stream FIL
*/
static void
print_text(msg,fil)
char *msg[];
FILE *fil;
{
char **line;
for(line = msg;*line != NULL;line++) {
fprintf(fil,"%s\n",*line);
}
}
/*****************************************************************************
*
* set a Font
*/
static void
set_font(font,turn_on,start,end)
int font; /* flag for font to set (e.g. Bold) */
int turn_on; /* should I start the font or end it?*/
char *end; /* strings to start and */
char *start; /* end the group that sets the font */
{
if(turn_on && Cformatting_char) {
if(!no_grouping) {
push_LaTeX_stack(end,Font,font);
}
output_str(start,'\0');
}
}
/*****************************************************************************
*
* change fontsize
*/
void set_fontsize(fontsize)
int fontsize; /* size of fonts default 10 */
{
if (fontsize<0)
{
p6("set_fontsize\nfontsize<0");
return;
}
if (fontsize==0)
{
p6("set_fontsize\nfontsize==0");
return;
}
if (!Cformatting_char)
{
return;
}
if (fontsize==8)
{
(void)RTFGetToken();
if (strcmp(rtfTextBuf,"\\up6")==0)
{
RTFUngetToken();
return; /* mostly we are before a footnote here */
} /* so we need no size-command, because */
RTFUngetToken(); /* LaTeX deel in a good way with it */
}
fputc('%',outfp);
output('\n',1);
if (initialised) /* in newenvironment {} not necessary */
{
push_LaTeX_stack("}",Font,0);
output_str("{",'\0');
}
if (fontsize<5)
{
output_str("\\tiny ",'\0');
return;
}
if (fontsize<7)
{
output_str("\\scriptsize ",'\0');
return;
}
if (fontsize<9)
{
output_str("\\small ",'\0');
return;
}
if (fontsize<11)
{
output_str("\\normalsize ",'\0');
return;
}
if (fontsize<13)
{
output_str("\\large ",'\0');
return;
}
if (fontsize<17)
{
output_str("\\Large ",'\0');
return;
}
if (fontsize<21)
{
output_str("\\LARGE ",'\0');
return;
}
if (fontsize<25)
{
output_str("\\huge ",'\0');
return;
}
output_str("\\Huge ",'\0');
}
/*****************************************************************************
*
* set higher or lower text
*/
static void
set_subsuper(param)
int param;
{
if(param == 0)
{ /* end of a sub/superscript */
while(!top_LaTeX_flags(Sub_Super))
{
if(pop_LaTeX_stack() == 0)
{
if(verbose)
{
fprintf(stderr,"%s: Failed to find end of sub/superscript\n",
progname);
}
return;
}
}
pop_LaTeX_stack(); /* pop off the '}' */
if(top_LaTeX_flags(Math)) pop_LaTeX_stack(); /* and pop math too */
return;
}
if (rtfMinor == rtfSuperScript)
{
(void)RTFGetToken();
if (strcmp(rtfTextBuf,"\\chftn")==0)
return; /* we are before a footnote here */
RTFUngetToken(); /* so we need no command, because */
} /* LaTeX deels with it in a good way */
output_str("$",'\0');
push_LaTeX_stack("$",Sub_Super,1);
if (initialised)
{
output_str(rtfMinor == rtfSuperScript ? "^{" : "_{",'\0');
push_LaTeX_stack("}",Sub_Super,rtfParam);
}
else
{
output_str(rtfMinor == rtfSuperScript ? "^" : "_",'\0');
output_str(" \\bgroup",'\0');
push_LaTeX_stack(" \\egroup",Sub_Super,rtfParam);
}
}
/*****************************************************************************
*
* set smallcaps
*/
static void
set_smallcaps()
{
fputc('%',outfp);
output('\n',1);
if (initialised)
{
output_str("{",'\0');
push_LaTeX_stack("}",Font,0);
}
output_str("\\sc ",'\0');
}
/*****************************************************************************
*
* Print a string, ensuring that we are in math mode at the time
*/
static void
in_math(str)
char *str;
{
output('$',0);
output_str(str,'\0');
output('$',0);
}
/*****************************************************************************
*
* Write a character, filling the the output text as we go. Characters
* special to LaTeX are treated appropriately.
*/
#define FILL_COLUMN 60 /* column to fill to */
#define MAX_COLUMN 80 /* max of column*/
static int column=0; /* current column */
static void
output(c,quote)
int c; /* The char to print */
int quote; /* quote LaTeX's special chars? */
{
char temp[25];
c &= '\377'; /* prevent sign extension */
if(isspace(c))
{
if(c == '\n')
{
fputc('\n',outfp);
column=0;
}
else
{
fputc(' ',outfp);
column++;
if (column>FILL_COLUMN)
{
fputc('\n',outfp);
column=0;
}
}
return;
}
if(quote) {
switch (rtf_ptr->char_attr.FontType) {
case rtfFFTech: /* A technical font */
{
char *str;
str = (c < 128) ? symbol[c] : symbol8[c & '\177'];
if(*str == '\0') {
/* if(verbose) { */
fprintf(stderr,"%s: Unknown Tech character: 0x%x\n",
progname,c);
/* } */
}
if(verbose) {
fprintf(stderr,"A Tech character: 0x%x\n",c);
}
in_math(str);
}
return;
default:
switch (c)
{ /* deal with various characters */
case '%': case '$':
case '#': case '&':
case '_':
fputc('\\',outfp);
column++;
break;
case '^':
output_str("$^{\\wedge}$",'\0');
return;
case '"':
if(translate_quotes)
c = (quotecount++ % 2) ? '\'' : '`';
else
c = '`';
fputc(german_dquotes ? '"' : c, outfp);
column++;
break;
case '<': case '>':
case '|':
sprintf(temp,"%c",c);
in_math(temp);
return;
case '{': case '}':
sprintf(temp,"\\%c",c);
in_math(temp);
return;
case '\\':
in_math("\\backslash");
return;
case '~':
in_math("\\sim");
c = ' ';
return;
default:
if(!isascii(c))
{
output_8bit(c);
return;
}
if(!isalnum(c) && !ispunct(c))
{
if (verbose)
fprintf(stderr,"%s: Unknown 7-bit character: 0x%x\n",
progname,c);
return;
}
break;
}
}
}
fputc(c,outfp);
column++;
}
/*****************************************************************************
*
* Output an entire word, without trying to quote any special characters.
* The character C is then output using output(), which allows proper page
* breaks.
*/
static void
output_str(str,c)
char *str;
int c;
{
int len = strlen(str);
int zeiger=0;
if(c != '\0')
{
output(c,1);
}
if (column==0 && str[0]=='\n')
str++;
if (str[0]=='\n')
fputc('%',outfp);
fprintf(outfp,"%s",str);
column+=len;
if (str[0] =='\n')
column=len;
if (str[len-1] == '\n')
column=0;
}
/*****************************************************************************
*
* Deal with special characters above \177.
*/
typedef struct Char8bit
{
int nr; /* RTF-code */
char *str; /* LaTeX command */
struct Char8bit *next;
}char8;
char8 *list_8bit; /* begin of the 8bit list */
char8 *help;
/*****************************************************************************
*
* write a 8bit character
*/
static void
output_8bit(c)
int c;
{
char *str;
help=list_8bit;
while(help->nr!=c && help->next!=NULL) /* search for the character*/
help=help->next;
if (help->nr==c)
{
output_str(help->str,'\0'); /* and write it */
}
else
{ /* character not found */
if(verbose)
{
static count=0;
fprintf(stderr,"%s: Unknown 8-bit character: 0x%x\n",progname,c);
if (count++<1||verbose>1)
fprintf(stderr," Have a look in the file .cod\n");
}
}
}
/*****************************************************************************
*
* read the file mac.code (or an other file e.g. ansi.code: use flag -C)
* and store the commands for characters with the 8bit set in the list
* "list_8bit"
*/
static void
read_code_file(codefile)
char *codefile;
{
char line[line_length];
int pos;
open_code_file(codefile);
if (fgets(line,line_length,fpcode)==NULL)
{
fprintf(stderr,"\n%s: Incorrect file a8bit \
\nat first there must be a number of the ascii character with msb set \
\n(between 128 and 255)\n",progname);
exit(1);
}
for (pos=23;line[pos]==' ';pos--);
line[pos+1]='\0'; /* cut the comment in the file*/
list_8bit=(struct Char8bit *)malloc((int)sizeof(struct Char8bit));
if (list_8bit==(struct Char8bit *)NULL)
{
fprintf(stderr,"%s: TCErr - cannot allocate a 8bit-character name\n", progname);
exit(1);
}
sscanf(line,"%d",&(list_8bit->nr));
list_8bit->str=StrSave(line+4);
if (list_8bit->nr<128 || list_8bit->nr>255)
{
fprintf(stderr,"\n%s: Incorrect file a8bit \
\nat first there must be a number of the ascii character with msb set \
\n(between 128 and 255)\n", progname);
exit(1);
}
list_8bit->next=NULL;
while (fgets(line,line_length,fpcode)!=NULL)
{
for (pos=23;line[pos]==' ';pos--);
line[pos+1]='\0';
help=(struct Char8bit *)malloc((int)sizeof(struct Char8bit));
if (help==(struct Char8bit *)NULL)
{
fprintf(stderr,"%s: SSErr - cannot allocate a 8bit-character name\n", progname);
exit(1);
}
help->next=list_8bit;
list_8bit=help;
sscanf(line,"%d",&(list_8bit->nr));
list_8bit->str=StrSave(line+4);
if (list_8bit->nr<128 || list_8bit->nr>255)
{
fprintf(stderr,"\n%s: Incorrect file a8bit \
\nat first there must be a number of the ascii character with msb set \
\n(between 128 and 255)\n", progname);
exit(1);
}
}
if (fpcode!=NULL) fclose(fpcode);
}
/*****************************************************************************
*
* write an errormassage to stderr
*
*/
static void
p6(proc_name)
char *proc_name; /*name of ther procedure where the mistake must be */
{
fprintf(stderr," %s: Problem in procedure %s\n",progname,proc_name);
fprintf(stderr," please call Erwin Wechtl\n");
fprintf(stderr," W""ortgasse 2/18\n");
fprintf(stderr," A-2500 Baden\n");
fprintf(stderr," Austria\n");
fprintf(stderr," Tel.: 43/2252/44686\n");
}
/*****************************************************************************
*
* set end af table
*/
static void
end_table()
{
table_mode=0;
if (top_LaTeX_flags(Tabular))
{
Cformatting_char=formatting_char;
Cformatting_para=formatting_para;
pop_LaTeX_stack();
tabinitold[0]='\0';
output_str("\n \n",'\0');
}
}
/*****************************************************************************
*
* translate each RTF-style into a new LaTeX environment
* and look for special WORD styles like heading (tranlated into section)
* or footer (ignored)
*/
LATEXStyle *LaTeXstyleList; /* we can't use the RTFstylelist
because we need more variables */
void DefineStyles()
{
RTFStyle *rtfstyle; /* the style to deel with */
LATEXStyle *LaTeXstyle; /* the style to deel with */
output_str("\n \n",'\0');
LaTeXstyleList=(LATEXStyle *)NULL;
for(rtfstyle=RTFGetStyle(-1);rtfstyle!=(RTFStyle *)NULL;rtfstyle=rtfstyle->rtfNextStyle)
{
LaTeXstyle=(LATEXStyle *)malloc(sizeof(struct LATEXStyle));
if (LaTeXstyle==NULL)
{
fprintf(stderr,"\n%s: Can't alloc LaTeXstyle\n",progname);
exit(1);
}
LaTeXstyle->stacktype=Undefined;
LaTeXstyle->BeginCommand[0] = LaTeXstyle->EndCommand[0] = '\0';
LaTeXstyle->special_WinwordStyle=TRUE;
if (!is_specialWORDstyle(rtfstyle,LaTeXstyle)) /* looking for special styles */
{
char commandbuf[80];
RTF_STACK rtf_save;
push_rtf_group();
rtf_save = rtf_current;
LaTeXstyle->special_WinwordStyle=FALSE;
LaTeX_name(rtfstyle->rtfSName);
strcpy(commandbuf,"\n\\");
strcat(commandbuf,"begin{");
strcat(commandbuf,rtfstyle->rtfSName);
strcat(commandbuf,"}\n");
strcpy(LaTeXstyle->BeginCommand,commandbuf);
strcpy(commandbuf,"\n\\");
strcat(commandbuf,"end{");
strcat(commandbuf,rtfstyle->rtfSName);
strcat(commandbuf,"}\n");
strcpy(LaTeXstyle->EndCommand,commandbuf);
output_str("\n% definition of ",'\0');
output_str(rtfstyle->rtfSName,'\0');
output_str("\n\\newenvironment{",'\0');
output_str(rtfstyle->rtfSName,'\0');
output_str("}{",'\0');
RTFExpandStyle(rtfstyle->rtfSNum);
LaTeXstyle->char_attr=rtf_ptr->char_attr;
LaTeXstyle->par_attr=rtf_ptr->par_attr;
LaTeXstyle->stacktype=NormalWORDstyle;
update_current();
output_str("}{",'\0');
while(pop_LaTeX_stack()) continue;
output_str("}\n",'\0');
rtf_current = rtf_save;
pop_rtf_group();
}
LaTeXstyle->rtfSNum=rtfstyle->rtfSNum;
LaTeXstyle->rtfSName=rtfstyle->rtfSName;
LaTeXstyle->LaTeXNextStyle=LaTeXstyleList;
LaTeXstyleList=LaTeXstyle;
}
if (fpland!=NULL) fclose(fpland);
}
/*****************************************************************************
*
* begin a style environment
*/
void setstylecommand(n)
int n; /* rtfStyleNumber */
{
LATEXStyle *LaTeXstyle;
RTFStyle *rtfstyle;
char buf[80];
if(!table_mode && top_LaTeX_flags(Tabular))
end_table();
LaTeXstyle=LaTeXstyleList;
while (LaTeXstyle!=NULL && LaTeXstyle->rtfSNum!=n) LaTeXstyle=LaTeXstyle->LaTeXNextStyle;
if (LaTeXstyle==NULL)
{
static int count=0;
rtfstyle=RTFGetStyle(n);
if (verbose>1 || (verbose && count++==0))
{
fprintf(stderr,"%s: There are some troubles with the style %s with the number %d, \n so this style is ignored\n",
progname,rtfstyle->rtfSName,n);
}
# ifdef notdef /* Don't know if this is needed anymore */
/* sprintf(buf,"\n%% The Style %s with the number %d may begin here\n",rtfstyle->rtfSName,n);
output_str(buf,'\0');
output_str("%%But rtf2LaTeX has had some troubles with it",'\0');
sprintf(buf,"\n% The Style %s with the number %d may end here\n",rtfstyle->rtfSName,n);
push_LaTeX_stack(buf,NormalWORDstyle,0);
*/
# endif /* notdef */
return;
}
if (LaTeXstyle->special_WinwordStyle) /* if heading,footer, ... */
{ /* use paragraph(character) formating only
if the flag -d is on */
Cformatting_para=formatting_sWORD&&formatting_para;
Cformatting_char=formatting_sWORD&&formatting_char;
}
else
{
update_current(); /* format */
rtf_current.par_attr=LaTeXstyle->par_attr;
rtf_current.char_attr=LaTeXstyle->char_attr;
rtf_ptr->par_attr=LaTeXstyle->par_attr;
rtf_ptr->char_attr=LaTeXstyle->char_attr;
rtf_current.LaTeX_stack = NULL;
rtf_current.prev = NULL;
}
output_str(LaTeXstyle->BeginCommand,'\0');
push_LaTeX_stack(LaTeXstyle->EndCommand,LaTeXstyle->stacktype,0);
}
/*****************************************************************************
*
* look in the file english.land (or an other file e.g. german.land:
* use flag -L)
* if this is a Spezial WORD style like heading, footer, ...
*/
int
is_specialWORDstyle(rtfstyle,LaTeXstyle)
RTFStyle *rtfstyle;
LATEXStyle *LaTeXstyle;
{
char line[line_length]; /* the line which is read from the file */
if (formatting_sWORD) /* if flag -d is on */
return(0); /* use WORD formate instead of LaTeX formate within header, ... */
fseek(fpland, 0, SEEK_SET);
while (fgets(line,line_length,fpland)!=NULL)
{
if (strncmp(rtfstyle->rtfSName,line,strlen(rtfstyle->rtfSName))==0)
{
LaTeXstyle->stacktype=SpecialWORDstyle;
if (strncmp(line+20," ",10)!=0)
sscanf(line+20,"%20s%20s",LaTeXstyle->BeginCommand,LaTeXstyle->EndCommand);
else
LaTeXstyle->BeginCommand[0] = LaTeXstyle->EndCommand[0] = '\0';
output_str("% ",'\0');
output_str(line+60,'\0');
return(1);
}
}
return(0);
}
/*****************************************************************************
*
* malloc for a string
*/
static char *StrSave (s)
char *s;
{
char *p;
if ((p = (char *)malloc (strlen (s) + 1)) == (char *) NULL)
fprintf(stderr,"%s: Error in malloc\n",progname);
return (strcpy (p, s));
}
/*****************************************************************************
*
* set the position of the Tabstops and output the begin environment
*/
static void
start_tabstops()
{
int i,j;
int width; /* width of table entry (twips) */
char buf[1];
if (top_LaTeX_flags(SpecialWORDstyle))
return; /* no tab stops in header, heading, ...*/
Cformatting_char=formatting_char&&formatting_table;
Cformatting_para=formatting_para&&formatting_table;
output_str("\n\\begin{tabbing}\n",'\0');
for(i = 0;i < NTABS;i++)
{
width = tabstops[i].pos;
if(i > 0)
width -= tabstops[i - 1].pos;
width=TW_TO_CA(width);
if (width<1)
continue;
for(j=1;j<=width;j++)
{
sprintf(buf,"%d",(j % 10));
output_str(buf,'\0');
}
output_str("\\=",'\0');
}
output_str("\\kill\n",'\0');
push_LaTeX_stack("\\end{tabbing}\n",Tabstops,0);
tabstopsInit();
tab=2;
}
/*****************************************************************************
*
* initialise the array of the Tabstops-positions
*/
static void
tabstopsInit()
{
int i;
for (i=0;i<NTABS;i++)
{
tabstops[i].pos=CA_TO_TW(i*defaultTabWidth);
tabstops[i].type=0;
}
ntabs=0;
}
/*****************************************************************************
*
* Stack stuff -- RTF and LaTeX grouping go on separate stacks
*
* pop the status stack, putting the free'd element on the free list
*/
static RTF_STACK *rtf_free_list = NULL;
static void
pop_rtf_group()
{
RTF_STACK *temp;
if(rtf_ptr->prev == NULL) {
fprintf(stderr,"%s: Attempt to pop an empty stack\n", progname);
abort();
}
temp = rtf_ptr->prev;
rtf_ptr->prev = rtf_free_list;
rtf_free_list = rtf_ptr;
rtf_ptr = temp;
}
/*
* push the RTF status stack
*/
static void
push_rtf_group()
{
RTF_STACK *temp;
/*#ifdef __riscos
register char *s,*d,*to;
#endif*/
if(rtf_free_list != NULL) {
temp = rtf_free_list;
rtf_free_list = rtf_free_list->prev;
} else {
if((temp = (RTF_STACK *)malloc(sizeof(RTF_STACK))) == NULL) {
fprintf(stderr,"%s: Can't allocate storage for stack\n",progname);
exit(1);
}
}
/*#ifdef __riscos
s = (char*)rtf_ptr; d = (char*)temp; to = s + sizeof(RTF_STACK);
while (s < to) {*d++ = *s++;}
#else*/
memcpy((char *)temp,(char *)rtf_ptr,sizeof(RTF_STACK));
/*#endif*/
temp->prev = rtf_ptr;
rtf_ptr = temp;
rtf_ptr->LaTeX_stack = NULL;
}
/*****************************************************************************
*
* Now the LaTeX stacks. Use the stack in the current rtf_ptr frame
*/
static LATEX_STACK *myTeX_free_list = NULL;
static int
pop_LaTeX_stack()
{
char *str;
LATEX_STACK *temp;
if(rtf_ptr->LaTeX_stack == NULL) {
return(0);
}
if (rtf_ptr->LaTeX_stack->type == SpecialWORDstyle)
{ /* reset formatting */
Cformatting_para =formatting_para; /* after heading, footer, .. */
Cformatting_char=formatting_char;
}
LaTeX_group--;
str = rtf_ptr->LaTeX_stack->str;
temp = rtf_ptr->LaTeX_stack->prev;
rtf_ptr->LaTeX_stack->prev = myTeX_free_list;
myTeX_free_list = rtf_ptr->LaTeX_stack;
rtf_ptr->LaTeX_stack = temp;
output_str(myTeX_free_list->str,'\0');
return(1);
}
/*
* push the string STR onto the LaTeX stack, with attributes TYPE and FLAGS
*/
static void
push_LaTeX_stack(str,type,flags)
char *str; /* string to save */
int type; /* type of string */
long flags; /* and corresponding flags */
{
LATEX_STACK *temp;
LaTeX_group++;
if(myTeX_free_list != NULL) {
temp = myTeX_free_list;
myTeX_free_list = myTeX_free_list->prev;
} else {
if((temp = (LATEX_STACK *)malloc(sizeof(LATEX_STACK))) == NULL) {
fprintf(stderr,"%s: Can't allocate storage for stack\n",progname);
exit(1);
}
}
temp->prev = rtf_ptr->LaTeX_stack;
rtf_ptr->LaTeX_stack = temp;
rtf_ptr->LaTeX_stack->str = str;
rtf_ptr->LaTeX_stack->type = type;
rtf_ptr->LaTeX_stack->flags = flags;
return;
}
/*****************************************************************************
*
* Return the flags of the proper type for the top element of the LaTeX stack
*/
static int
top_LaTeX_flags(type)
int type;
{
return((rtf_ptr->LaTeX_stack != NULL && rtf_ptr->LaTeX_stack->type == type) ?
1 : 0);
}
/*****************************************************************************/
static void
open_code_file (codefile)
char *codefile;
{
char *filename;
char line[line_length];
char c;
if((filename = malloc(strlen(codefile) + strlen(RTFDIR) + 7)) == NULL)
{
fprintf(stderr,"%s: Error in malloc\n",progname);
exit(3);
}
strcpy(filename,RTFDIR);
#if (!defined (THINK_C)) && (!defined (__riscos))
strcat(filename,"/");
#endif /* !THINK_C */
#ifdef __riscos
strcat(filename,"code."); strcat(filename,codefile);
#else
strcat(filename,codefile);
if ((strchr(codefile,'.')) == NULL)
strcat(filename,".code");
#endif
if((fpcode = fopen(filename,"r")) == NULL)
{
fprintf(stderr,"%s: Can't open %s\n",progname,filename);
exit(1);
}
free(filename);
if (fgets(line,line_length,fpcode)==NULL)
{
fprintf(stderr,"\n%s: Incorrect file a8bit \
\nthere must be a comment in the first line\n",
progname);
exit(1);
}
}
static void
open_land_file (landfile)
char *landfile;
{
char *filename;
if((filename = malloc(strlen(landfile) + strlen(RTFDIR) + 7)) == NULL)
{
fprintf(stderr,"%s: Error in malloc\n",progname);
exit(3);
}
strcpy(filename,RTFDIR);
#if (!defined (THINK_C)) && (!defined (__riscos))
strcat(filename,"/");
#endif /* !THINK_C */
#ifdef __riscos
strcat(filename,"land."); strcat(filename,landfile);
#else
strcat(filename,landfile);
if ((strchr(landfile,'.')) == NULL)
strcat(filename,".land");
#endif
if((fpland = fopen(filename,"r")) == NULL) {
fprintf(stderr,"%s: Can't open %s\n",progname,filename);
exit(1);
}
free(filename);
}